import React from 'react';
import ReactFlow, {applyEdgeChanges, applyNodeChanges, ReactFlowProvider} from 'react-flow-renderer';
import "./App.css"
import Sidebar from "./components/Sidebar";
import CustomNode from "./components/node/CustomNode";

class App extends React.Component {

    constructor() {
        super();
        this.state = {
            reactFlowWrapper: null,
            reactFlowInstance: null,
            nodeName: "",
            nodeTypes: {
                selectorNode: CustomNode,
            },
            currentNode: null,
            nodes: [
                {
                    id: '1',
                    type: 'input',
                    data: {label: 'Input Node'},
                    targetPosition: 'left',
                    sourcePosition: 'right',
                    position: {x: 250, y: 25},
                },
                {
                    id: '2',
                    type: 'selectorNode',
                    data: {color: "#000"},
                    targetPosition: 'left',
                    sourcePosition: 'right',
                    position: {x: 300, y: 150},
                },
                {
                    id: '3',
                    type: 'output',
                    data: {label: 'Output Node'},
                    targetPosition: 'left',
                    sourcePosition: 'right',
                    position: {x: 250, y: 250},
                },
            ],
            edges: [
                {id: 'e1-2', source: '1', target: '2'},
                {id: 'e2-3', source: '2', target: '3', animated: true},
            ]
        }
    }

    componentDidMount() {
        let {currentNode, nodes} = this.state;
    }

    render() {
        let that = this;
        let {nodes, edges, nodeName, nodeTypes} = that.state;
        return <div className="dndflow">
            <ReactFlowProvider>
                <Sidebar/>
                <div className="reactflow-wrapper" ref="reactFlowWrapper">
                    <ReactFlow
                        nodeTypes={nodeTypes}
                        onInit={reactFlowInstance => this.setState({reactFlowInstance: reactFlowInstance})}
                        onDrop={(event) => {
                            event.preventDefault();
                            const reactFlowBounds = this.refs.reactFlowWrapper.getBoundingClientRect();
                            const type = event.dataTransfer.getData('application/reactflow');
                            const nodeName = event.dataTransfer.getData('application/reactflow-nodename');

                            // check if the dropped element is valid
                            if (typeof type === 'undefined' || !type) {
                                return;
                            }

                            const position = this.state.reactFlowInstance.project({
                                x: event.clientX - reactFlowBounds.left,
                                y: event.clientY - reactFlowBounds.top,
                            });
                            const newNode = {
                                id: "" + new Date().getTime(),
                                type,
                                position,
                                targetPosition: 'left',
                                sourcePosition: 'right',
                                data: {label: nodeName},
                            };
                            this.setState({nodes: this.state.nodes.concat(newNode)});
                        }}
                        onDragOver={(event) => {
                            event.preventDefault();
                            event.dataTransfer.dropEffect = 'move';
                        }}
                        defaultNodes={nodes}
                        defaultEdges={edges}
                        onConnect={(params) => {
                            edges.push({
                                id: `e${params.source}-${params.target}`,
                                source: params.source,
                                target: params.target
                            });
                            this.setState({edges: edges})
                        }}
                        onNodeContextMenu={(event, node) => {
                            event.preventDefault();
                            this.setState({
                                nodes: this.state.nodes.filter(x => x.id !== node.id),
                                edges: this.state.edges.map(y => {
                                    if ((y.target === node.id) || (y.source === node.id)) {
                                        return null;
                                    }
                                    return y;
                                }).filter(z => !!z)
                            })
                        }}
                        onNodeClick={(event, node) => this.setState({currentNode: node})}
                        onNodesChange={(nodeChange) => this.setState({nodes: applyNodeChanges(nodeChange, this.state.nodes)})}
                        onEdgesChange={(edgeChange) => this.setState({edges: applyEdgeChanges(edgeChange, this.state.edges)})}
                        fitView>
                        <div className="updatenode__controls">
                            <label>label:</label>
                            <input type="text" value={nodeName} onChange={(evt) => this.setState({
                                nodeName: evt.target.value, nodes: this.state.nodes.map(x => {
                                    if (x.id === '1') {
                                        // x.data.label = evt.target.value
                                        x.data = {
                                            ...x.data,
                                            label: evt.target.value,
                                        };
                                    }
                                    return x
                                })
                            })}/>
                            <button onClick={() => {
                                alert(JSON.stringify(this.state.reactFlowInstance.getNodes()))
                                alert(JSON.stringify(this.state.reactFlowInstance.getEdges()))
                            }
                            }>测试
                            </button>
                        </div>
                    </ReactFlow>
                </div>
            </ReactFlowProvider>
        </div>
    }
}

export default App;
